package cn.wzptsoft.tinymallbe.interceptor;

import cn.wzptsoft.common.constant.RespCodeEnum;
import cn.wzptsoft.common.exception.BizException;
import cn.wzptsoft.common.utils.JwtUtils;
import cn.wzptsoft.tinymallbe.entity.User;
import cn.wzptsoft.tinymallbe.security.ThreadContext;
import cn.wzptsoft.tinymallbe.service.UserService;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 接口访问 登录验证
 * <a href="https://blog.csdn.net/weixin_46649054/article/details/118355986">HandlerInterceptor拦截器使用</a>
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {

    private final UserService userService;

    public LoginInterceptor(UserService userService) {
        this.userService = userService;
    }

    /**
     * 预处理，在业务处理器处理请求之前被调用，可以进行登录拦截，编码处理、安全控制、权限校验等处理
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 跨域支持
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            return true;
        }
        String bearerToken = request.getHeader("Authorization");
        if (ObjectUtils.isEmpty(bearerToken) || !bearerToken.startsWith("Bearer")) {
            throw new BizException(RespCodeEnum.UNAUTHORIZE);
        }
        String[] tokens = bearerToken.split(" ");
        if (!(tokens.length == 2)) {
            throw new BizException(RespCodeEnum.UNAUTHORIZE);
        }
        String jwt = tokens[1];
        // 解决请求头中的jwt
        String subject = JwtUtils.getSubject(jwt);
        // 查询数据库 得到用户完整信息
        User user = userService.getUserById(Long.parseLong(subject));
        if (user == null) {
            throw new BizException(RespCodeEnum.UNAUTHORIZE);
        }
        ThreadContext.setUser(user);
        return true;
    }

    /**
     * 上下文属性值清除 防止内存泄漏
     * 返回处理，在DispatcherServlet完全处理完请求后被调用，可用于清理资源等。已经渲染了页面。
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ThreadContext.clear();
    }
}
